Skip to content

Common 3D Navigation and Settings for the Editor Viewport#10439

Closed
FabiPhun wants to merge 943 commits intoFacepunch:masterfrom
FabiPhun:ImprovedViewportControls
Closed

Common 3D Navigation and Settings for the Editor Viewport#10439
FabiPhun wants to merge 943 commits intoFacepunch:masterfrom
FabiPhun:ImprovedViewportControls

Conversation

@FabiPhun
Copy link
Copy Markdown

@FabiPhun FabiPhun commented Apr 10, 2026

Pull Request

Thanks for contributing to s&box ❤️
Please fill out the sections below to help us review your change efficiently.


Summary

Rewrote the 3D Viewport Navigation within the S&box editor, to be closely resembling common 3D Software while keeping the "WASD" and camera "look around" functionality (flying camera in short) fully functional.

Motivation & Context

I have posted a feature request on the S&box GitHub discussing the poor navigation.

Having talked to other members on the S&box Discord, people seemed quite enthused with the idea of a navigation experience resembling most common 3D Software, I therefore created a JS prototype within a week as a proof of concept.

Fixes:

  • Merged the Pan-logic, from FirstPersonCamera with OrbitCamera
  • Rewrote Orbit / Pan / Zoom logic to use distance aware navigation
  • Removed unused / illogical settings within the Scene View settings
  • Added new settings to support the new Orbit / Pan / Zoom

Implementation Details

Files edited:

  • SceneViewportWidget.cs
  • SceneViewportExtensions.cs
  • EditorPreferences.cs
  • PageSceneView.cs

  • Works in both Perspective and Orthographic Views

  • Point Specific Navigation
    A ray is shot from mousePos/Screenspace, when it hits something it uses the distance and position to change the zoom speed, the point around which the camera orbits and it gives the pan the necessary data to stick the point where the user clicked to the mouse cursor ( includes FOV calculations' ).

  • SceneViewportWidget.cs
    I had quite the fight with some of the specific exception logic and errors while adapting the new Inputs - I did some hacks here and there and would recommend the FP to find a new approach to using exceptions and Inputs within the viewport.

  • Navigation Styles
    I added the option for Software specific Navigation Styles instead of just one set style, the reasoning here is so anyone can use their favorite Style of Navigation.

Screenshots / Videos (if applicable)

Showcase Video:
https://github.com/user-attachments/assets/fe579fe6-38bc-4a66-978f-1213164f0b44

Settings Screenshot:
Screenshot_4

Pull Request

##Checklist

  • Code follows existing style and conventions
  • No unnecessary formatting or unrelated changes
  • Public APIs are documented (if applicable)
  • Unit tests added where applicable and all passing
  • I’m okay with this PR being rejected or requested to change 🙂

garrynewman and others added 30 commits March 6, 2026 06:16
Avoid RenderGroupKey allocations

This would allocate a lot easily 60Mb/s.
Instead of a dedicated struct we now compute a 64bit hash and use that for render grouping.

Remove per frame HashSet, List and LINQ allocations
* More accurate and less allocation heavy version of Task.Delay

- Shoot a single task delay for longer intervals
- Only use expensive polling for the last sub threshold

* Avoid ExecutingJob allocations when not tracking jobs
* Start moving SSR to bindless

* Classify pass stub

* Separable bilateral upscale, 0.3ms > 0.08ms, not happy with it still

* start classify and intersect indirect

* Commandlist support for UAV barriers and clearing a texture and gpubuffer

* Simplify this, move classify to it's own shader

* All indirect

* ResourceState.IndirectArgument missing from ResourceStateToVulkanFlags switch

* Fix indirect, all works

* classify doesnt get skybox

* Add Clear method to CommandList for clearing render target colors

* bilateral upscale indirect too

* Cleanup

* Simplify bilateral upscale, With RADIUS=1, separable saves only 3 taps (6 vs 9), but costs 3 barriers + shared memory + atomics — the synchronization overhead far exceeds 3 extra texture loads of doing it with a normal X Y loop

* Dotnet format, increase roughness threshold (we can afford it 😘 ) and dont need to discard these buffers on disable

* compile shaders

* this shouldnt be a property

* Add FillGPUBuffer method for efficient buffer filling using native GPU commands
CollisionEventSystem is quite alloc heavy especially the action wiring causes 10+ heap allocations per collider.
Collect pending acks in List rather than spamming async tasks.
Process List in Tick.
So we don't allocate when a GameObejct doesn't have any tags
Fast & alloc free pass for GameTags.SetFrom
* Remove unnecessary static singletons in MainMenu code

* Empty SceneWorld delete queues during shutdown

* Dresser cancel async load operation on destroy

* Use reflection to null references to static native resources on shutdown

This way we don't  have to remember doing this manually.

* Fix SoundOcclusionSystem using static lists to reference resources

* Sound System: Use weak references to refer to scenes

* Cleanup static logging listeners that kept strong refs to panels

* UISystem Cleanup, make sure all panel/stylesheet refs are released

* RenderTarget and RenderAttributes shutdown cleanup

* Rework AvatarLoader, ThumbLoader & HTTPImageLoader Cache

First try to go through ResourceLibrary.WeakIndex which might already hold the texture.

If there is no hit, go through a second cache that caches HTTP & Steam API response bytes instead of textures.
We want to cache the response bytes rather than the actual Texture, so stuff cached sits in RAM not VRAM.
Before avatars and thumbs would reside in VRAM.

* Fix rendertarget leak in CommandList.Attr.SetValue

GetDepthTarget() / GetColorTarget() return a new strong handle (ref count +1).
We need to DestroyStrongHandle()  that ref. So handles don't leak.

* Call EngineLoop.DrainFrameEndDisposables before shutdown

* NativeResourceCache now report leaks on shutdown

* Override Resource.Destroy for native resources, kill stronghandles

* Deregister SceneWorld from SceneWorld.All during destruction

* Ensure async texture loading cancels on shutdown

* SkinnedModelRender bonemergetarget deregister from target OnDisabled

* Clear shaderMaterials cache during shutdown

* Refactor Shutdown code

Mostly renaming methods from Clear() -> Shutdown()
Adding separate GlobalContext.Shutdown function (more aggressive than GlobalContext.Reset).
Clear some static input state.

* Deregister surfaces from Surface.All in OnDestroy

* RunAllStaticConstructors when loading a mount

* Advanced managed resource leak tracker enabled via `resource_leak_tracking 1`

Works by never pruning the WeakTable in NativeResourceCache.
So we can check for all resources if they are still being held on to and log a callstack.
* Support types like Curve, Gradient, ParticleGradient in movies
* Fix TransformOperation.OnReduce: old implementation was nonsense, could stack overflow
* Add optional filePath parameter to GenerateScreenshotFilename
* Force movie project to save even if we don't think it's changed
* ITemporaryEffect.IsActive pseudo-property for movie recordings
* Add ITrack.GetPathString() extension
* Safety when trying to compress a sample block
* Skip updating playback rate on renderers with a bone merge target
* Move PropertySignal<T>.FromSamples to PropertySignal
* Fix view not always updating when zooming
* Enabled tracks defaults to false when applying
* Movie export: manually call Scene.EditorTick, pause updates elsewhere (fixes #10137)
* CanMakeTrackFromProperties: default to only allowing user types
Introduced in Facepunch/sbox#4242 , which added some additional panel cleanup
Ignore static members when serializing or cloning components, makes no sense and breaks cloning with Expression Trees (that was introduced in Facepunch/sbox#4202)

Fixes #10161
Synthesizer never disposed its SpeechSynthesizer, causing background VoiceSynthesis threads to accumulate indefinitely (30+ seen in crash dumps).
This may have caused crashes in TTS heavy games like DXRP.

In addition we now properly terminate the SoundStream so SoundHandle.IsPlaying will become false after the stream has been played.

See: #4184
Needs to be rethought, it gets in the way often -- keeping view handle though
* Sync localisation files to clients thru network files
* Changing lang triggers Panel.LanguageChanged again, so we can rebuild panels, labels, etc.
* Init ActiveFriends as Enumerable.Empty

* Snip IconPanel logging its url
lolleko and others added 28 commits April 9, 2026 08:46
Fix transform update regression from 7b853ce

Rotation.AlmostEqual default threshold was too loose (0.0001 dot-product ~ 1.62° angular tolerance), causing SetLocalTransform to silently drop small transform updates.

- Rotation.AlmostEqual: default delta 0.0001 -> 0.0000001 (~0.05°), use MathF.Abs(Dot) to handle antipodal quaternions (q === -q)
- Transform.AlmostEqual: use Rotation's own default instead of passing the Position/Scale delta to a dot-product metric
Add `DeferGeneration` property to skip navmesh generation during scene load, allowing tiles to be generated and unloaded on demand at runtime.

New public API:
- `NavMesh.DeferGeneration` - skip tile generation on load
- `NavMesh.RequestTileGeneration`/`RequestTilesGeneration` - fire-and-forget via cache loop
- `NavMesh.UnloadTile`/`UnloadTiles` - remove tiles from the navmesh
* preload resolutions on init
- rewrote CameraOrbit logic
- moved panning from FirstPersonCamera to CameraOrbit
- changed logic within SceneViewportWidget / PageSceneView / EditorPreferences to adjust for new SceneEditorExtension changes
Managed will queue deletion no need to check for proper destruction this early
- final code clean-up
- fixed a issue where when the raycast within zoom didn't hit anything, it used the world origin as the reference point instead of the last hit performed by either orbit/zoom or pan
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.